﻿using System;
using System.Web;
using System.Web.Security;
using DotNetOpenAuth.AspNet;
using Microsoft.AspNet.Membership.OpenAuth;

namespace DemoASPNET.Account
{
  public partial class RegisterExternalLogin : System.Web.UI.Page
  {
    protected string ProviderName
    {
      get { return (string)ViewState["ProviderName"] ?? String.Empty; }
      private set { ViewState["ProviderName"] = value; }
    }

    protected string ProviderDisplayName
    {
      get { return (string)ViewState["ProviderDisplayName"] ?? String.Empty; }
      private set { ViewState["ProviderDisplayName"] = value; }
    }

    protected string ProviderUserId
    {
      get { return (string)ViewState["ProviderUserId"] ?? String.Empty; }
      private set { ViewState["ProviderUserId"] = value; }
    }

    protected string ProviderUserName
    {
      get { return (string)ViewState["ProviderUserName"] ?? String.Empty; }
      private set { ViewState["ProviderUserName"] = value; }
    }

    protected void Page_Load()
    {
      if (!IsPostBack)
      {
        ProcessProviderResult();
      }
    }

    protected void logIn_Click(object sender, EventArgs e)
    {
      CreateAndLoginUser();
    }

    protected void cancel_Click(object sender, EventArgs e)
    {
      RedirectToReturnUrl();
    }

    private void ProcessProviderResult()
    {
      // Process the result from an auth provider in the request
      ProviderName = OpenAuth.GetProviderNameFromCurrentRequest();

      if (String.IsNullOrEmpty(ProviderName))
      {
        Response.Redirect(FormsAuthentication.LoginUrl);
      }

      // Build the redirect url for OpenAuth verification
      var redirectUrl = "~/Account/RegisterExternalLogin";
      var returnUrl = Request.QueryString["ReturnUrl"];
      if (!String.IsNullOrEmpty(returnUrl))
      {
        redirectUrl += "?ReturnUrl=" + HttpUtility.UrlEncode(returnUrl);
      }

      // Verify the OpenAuth payload
      var authResult = OpenAuth.VerifyAuthentication(redirectUrl);
      ProviderDisplayName = OpenAuth.GetProviderDisplayName(ProviderName);
      if (!authResult.IsSuccessful)
      {
        Title = "External login failed";
        userNameForm.Visible = false;

        ModelState.AddModelError("Provider", String.Format("External login {0} failed.", ProviderDisplayName));

        // To view this error, enable page tracing in web.config (<system.web><trace enabled="true"/></system.web>) and visit ~/Trace.axd
        Trace.Warn("OpenAuth", String.Format("There was an error verifying authentication with {0})", ProviderDisplayName), authResult.Error);
        return;
      }

      // User has logged in with provider successfully
      // Check if user is already registered locally
      if (OpenAuth.Login(authResult.Provider, authResult.ProviderUserId, createPersistentCookie: false))
      {
        RedirectToReturnUrl();
      }

      // Store the provider details in ViewState
      ProviderName = authResult.Provider;
      ProviderUserId = authResult.ProviderUserId;
      ProviderUserName = authResult.UserName;

      // Strip the query string from action
      Form.Action = ResolveUrl(redirectUrl);

      if (User.Identity.IsAuthenticated)
      {
        // User is already authenticated, add the external login and redirect to return url
        OpenAuth.AddAccountToExistingUser(ProviderName, ProviderUserId, ProviderUserName, User.Identity.Name);
        RedirectToReturnUrl();
      }
      else
      {
        // User is new, ask for their desired membership name
        userName.Text = authResult.UserName;
      }
    }

    private void CreateAndLoginUser()
    {
      if (!IsValid)
      {
        return;
      }

      var createResult = OpenAuth.CreateUser(ProviderName, ProviderUserId, ProviderUserName, userName.Text);
      if (!createResult.IsSuccessful)
      {

        ModelState.AddModelError("UserName", createResult.ErrorMessage);

      }
      else
      {
        // User created & associated OK
        if (OpenAuth.Login(ProviderName, ProviderUserId, createPersistentCookie: false))
        {
          RedirectToReturnUrl();
        }
      }
    }

    private void RedirectToReturnUrl()
    {
      var returnUrl = Request.QueryString["ReturnUrl"];
      if (!String.IsNullOrEmpty(returnUrl) && OpenAuth.IsLocalUrl(returnUrl))
      {
        Response.Redirect(returnUrl);
      }
      else
      {
        Response.Redirect("~/");
      }
    }
  }
}